#!/bin/bash

# Configuration by env:
#  - GIT_BASEURL - base url of git repos
#  - GIT_PREFIX - whose repo to clone
#  - GIT_SUFFIX - git component dir suffix (default .git)
#  - COMPONENT - component to clone
#  - BRANCH - git branch
#  - NO_CHECK=1 - disable signed tag checking
#  - CLEAN=1 - remove previous sources (use git up vs git clone)
#  - FETCH_ONLY=1 - fetch sources but do not merge
#  - IGNORE_MISSING=1 - exit with code 0 if remote branch doesn't exists
#  - GIT_REMOTE=<remote-name> - use "remote" from git configuration instead of
#    explicit URL
#  - REPO=dir - specify repository directory, component will be guessed based
#    on basename

function print_headers() {
if [ -z "$GIT_OPTIONS" ]; then
    GIT_INFOS="$GIT_URL $BRANCH"
else
    GIT_INFOS="$GIT_URL $BRANCH (options: $GIT_OPTIONS)"
fi

echo "-> Updating sources for $COMPONENT..."
echo "--> Fetching from $GIT_INFOS..."
}

set -e
[ "$DEBUG" = "1" ] && set -x

[ -n "$REPO" ] && COMPONENT="$(basename "$REPO")"

# Special case for qubes-builder itself
[ "$REPO" == "." ] && COMPONENT="builder"

[ -z "$COMPONENT" ] && { echo "ERROR: COMPONENT not set!"; exit 1; }

[ -z "$REPO" ] && REPO="$COMPONENT"

url_var="GIT_URL_${COMPONENT//-/_}"

if [ -n "$GIT_URL" ]; then
    GIT_URL="$GIT_URL"
elif [ -n "${!url_var}" ]; then
    GIT_URL="${!url_var}"
else
    GIT_URL=$GIT_BASEURL/$GIT_PREFIX$COMPONENT$GIT_SUFFIX
fi

# Override GIT_URL with GIT_REMOTE if given
[ -n "$GIT_REMOTE" ] && GIT_URL=$GIT_REMOTE

branch_var="BRANCH_${COMPONENT//-/_}"

if [ -n "${!branch_var}" ]; then
    BRANCH="${!branch_var}"
fi

GIT_OPTIONS=
if [ "$GIT_CLONE_FAST" = "1" ]; then
    GIT_OPTIONS+="--depth=1"
fi

fresh_clone=0
if [ "$REPO" == "." ] || [ -d "$REPO" ] && [ "$CLEAN" != '1' ]; then
    cd $REPO
    if [ "$(git rev-parse --is-shallow-repository)" == "true" ] && [ "$GIT_CLONE_FAST" != "1" ]; then
        GIT_OPTIONS+="--unshallow"
    fi
    print_headers
    if ! git fetch $GIT_OPTIONS -q "$GIT_URL" --tags $BRANCH; then
        if [ "$IGNORE_MISSING" == "1" ]; then exit 0; else exit 1; fi
    fi
    VERIFY_REF=FETCH_HEAD
    # shellcheck disable=SC2103
    cd - >/dev/null
else
    rm -rf $REPO
    if [ "$(git rev-parse --is-shallow-repository)" == "true" ] && [ "$GIT_CLONE_FAST" != "1" ]; then
        GIT_OPTIONS+="--unshallow"
    fi
    print_headers
    if ! git clone $GIT_OPTIONS -n -q -b $BRANCH "$GIT_URL" $REPO; then
        if [ "$IGNORE_MISSING" == "1" ]; then exit 0; else exit 1; fi
    fi
    VERIFY_REF=HEAD
    fresh_clone=1
fi

elementIn () {
  # $1: element to check for
  # $2: array to check for element in
  local element
  for element in "${@:2}"; do [[ "$element" == "$1" ]] && return 0; done
  return 1
}

verify=true
if [ "$NO_CHECK" == "1" ] || elementIn "$COMPONENT" ${NO_CHECK[@]}; then
    echo "--> $COMPONENT has NO_CHECK enabled"
    echo "--> NOT Verifying tags..."
    verify=false
fi

if [ "$verify" == "true" ]; then
    echo "--> Verifying tags..."
    if ! "$(dirname "$0")/verify-git-tag" $REPO $VERIFY_REF; then
        # if verfication failed, remove fetched content to make sure we'll not
        # use it
        if [ "$fresh_clone" -eq 1 ]; then
            rm -rf "$REPO"
        else
            rm -f "$REPO"/.git/FETCH_HEAD
        fi
        exit 1
    fi
fi

if [ "$FETCH_ONLY" == "1" ]; then
    exit 0
fi

CURRENT_BRANCH="$(cd $REPO; git branch | sed -n -e 's/^\* \(.*\)/\1/p')"
if [ "$CURRENT_BRANCH" != "$BRANCH" ] || [ "$VERIFY_REF" == "HEAD" ]; then
    pushd $REPO &> /dev/null
    red="$(echo -e '\033[1;31m')"
    green="$(echo -e '\033[1;32m')"
    normal="$(echo -e '\033[0;0m')"
    if [ -n "$(git name-rev --name-only $BRANCH 2> /dev/null)" ]; then
        echo "--> Switching branch from $CURRENT_BRANCH branch to ${green}$BRANCH${normal}"
        git checkout $BRANCH || exit 1
    else
        echo -e "--> Switching branch from $CURRENT_BRANCH branch to new ${red}$BRANCH${normal}"
        git checkout FETCH_HEAD -b $BRANCH || exit 1
    fi
    popd &> /dev/null
fi

if [ "$VERIFY_REF" == "FETCH_HEAD" ]; then
    echo "--> Merging..."
    pushd $REPO &> /dev/null
    git merge --commit -q FETCH_HEAD
    popd &> /dev/null
fi

echo
